﻿using System;
using System.Linq;
using System.Data.SQLite;
using CompactMapper.Orm.Contracts;
using CompactMapper.Orm.Extensions;
using CompactMapper.Orm.UnitOfWork.Commands.Implementations;
using System.Collections;
using System.Collections.Generic;

namespace CompactMapper.Orm.UnitOfWork.Mappings
{
    internal class DeleteMappings : CommandMappingsBase
    {
        internal DeleteMappings(TablesTree mappingsTree)
            : base(mappingsTree)
        {
        }

        protected override void CreateSpecificMappings(Tree<Table> tablesTree)
        {
            foreach (var child in tablesTree.Children)
            {
                if (child.Node.DeleteCommand == null)
                {
                    child.Node.DeleteCommand = new DeleteCommand(child.Node);
                }
                CreateSpecificMappings(child);
            }
        }

        public void Run<T>(SQLiteConnection connection)
        {
            var mapping = TablesTree.GetTreeFor(typeof(T));
            mapping.Node.DeleteCommand.Run(connection);
        }

        public void Run<T>(SQLiteConnection connection, IKey key)
            where T : class, IKeyedPersistent
        {
            var mapping = TablesTree.GetTreeFor(typeof(T));
            RunCommandsAtTopLevel<T>(mapping, connection, key);
        }

        private static void RunCommandsAtTopLevel<T>(Tree<Table> tablesTree, SQLiteConnection connection, IKey key)
            where T : class, IKeyedPersistent
        {
            var linesReader = new LinesReader(connection, tablesTree.Node, key);
            var toDelete = linesReader.Cast<T>().SingleOrDefault();

            if (toDelete == null)
                return;

            //var thisTable = tablesTree.Node;
            //var thisTableName = thisTable.Name;

            //foreach (var childtablesTree in tablesTree.Children)
            //{
            //    var childTable = childtablesTree.Node;
            //    var relation = childTable.GetRelationshipWith(thisTableName);
            //    if (relation != Relationship.None)
            //    {
            //        RunCommandsIndirectRelation(childtablesTree, connection, thisTableName, key);
            //    }
            //}
            tablesTree.Node.DeleteCommand.Run(connection, key);
        }


        private static void RunCommandsIndirectRelation(Tree<Table> tablesTree, SQLiteConnection connection, String parentTableName, IKey parentTableKey)
        {
            IEnumerable<IKeyedPersistent> allAtThisLevel;
            using (var linesReader = new LinesReader(connection, tablesTree.Node, parentTableName, parentTableKey))
                allAtThisLevel = linesReader.Cast<IKeyedPersistent>().ToArray();
            foreach (var topLevel in allAtThisLevel)
            {
                var theKey = topLevel.Key;

                var thisTable = tablesTree.Node;
                var thisTableName = thisTable.Name;

                foreach (var childtablesTree in tablesTree.Children)
                {
                    var childTable = childtablesTree.Node;

                    var relationship = childTable.GetRelationshipWith(thisTableName);
                    if (relationship != Relationship.None)
                    {
                        RunCommandsIndirectRelation(childtablesTree, connection, thisTableName, theKey);
                    }
                }
                tablesTree.Node.DeleteCommand.Run(connection, theKey);
            }
        }
    }
}